package main

import (
	"context"
	"fmt"
	"runtime"
	"time"
)

func monitor2(ctx context.Context, number int) {
	for {
		select {
		case v := <-ctx.Done():
			fmt.Printf("monitor2: %v, the received channel value is: %v, ending\n", number, v)
			return
		default:
			fmt.Printf("monitor2: %v in progress...\n", number)
			time.Sleep(2 * time.Second)
		}
	}
}

func monitor1(ctx context.Context, number int) {
	for {
		go monitor2(ctx, number)
		select {
		case v := <-ctx.Done():
			fmt.Printf("monitor1: %v, the received channel value is: %v, ending\n", number, v)
			return
		default:
			fmt.Printf("monitor1: %v in progress...\n", number)
			time.Sleep(2 * time.Second)
		}
	}
}

func main() {
	ctx, cancel := context.WithCancel(context.Background())

	for i := 1; i <= 5; i++ {
		go monitor1(ctx, i)
	}

	time.Sleep(time.Second)

	// Close all goroutines
	cancel()

	time.Sleep(5 * time.Second)

	fmt.Println(runtime.NumGoroutine())
	println("main program exit!!")

}
